allow separate events for each answer in the HumanTaskAgent

Andrew Cantino 10 years ago
parent
commit
2c820e8af2
2 changed files with 58 additions and 23 deletions
  1. 15 3
      app/models/agents/human_task_agent.rb
  2. 43 20
      spec/models/agents/human_task_agent_spec.rb

+ 15 - 3
app/models/agents/human_task_agent.rb

@@ -62,6 +62,8 @@ module Agents
62 62
       which contain `key` and `text`.  For _free\\_text_, the special configuration options are all optional, and are
63 63
       `default`, `min_length`, and `max_length`.
64 64
 
65
+      By default, all answers are emitted in a single event.  If you'd like separate events for each answer, set `separate_answers` to `true`.
66
+
65 67
       # Combining answers
66 68
 
67 69
       There are a couple of ways to combine HITs that have multiple `assignments`, all of which involve setting `combination_mode` at the top level.
@@ -105,7 +107,7 @@ module Agents
105 107
             }
106 108
           }
107 109
 
108
-      Resulting events will have the original `answers`, as well as the `poll` results, and a field called `best_answer` that contains the best answer as determined by the poll.
110
+      Resulting events will have the original `answers`, as well as the `poll` results, and a field called `best_answer` that contains the best answer as determined by the poll.  (Note that `separate_answers` won't work when doing a poll.)
109 111
 
110 112
       # Other settings
111 113
 
@@ -351,8 +353,18 @@ module Agents
351 353
 
352 354
               log "Poll HIT created with ID #{poll_hit.id} and URL #{poll_hit.url}.  Original HIT: #{hit_id}", :inbound_event => inbound_event
353 355
             else
354
-              event = create_event :payload => payload
355
-              log "Event emitted with answer(s)", :outbound_event => event, :inbound_event => inbound_event
356
+              if options[:separate_answers]
357
+                payload['answers'].each.with_index do |answer, index|
358
+                  sub_payload = payload.dup
359
+                  sub_payload.delete('answers')
360
+                  sub_payload['answer'] = answer
361
+                  event = create_event :payload => sub_payload
362
+                  log "Event emitted with answer ##{index}", :outbound_event => event, :inbound_event => inbound_event
363
+                end
364
+              else
365
+                event = create_event :payload => payload
366
+                log "Event emitted with answer(s)", :outbound_event => event, :inbound_event => inbound_event
367
+              end
356 368
             end
357 369
           end
358 370
 

+ 43 - 20
spec/models/agents/human_task_agent_spec.rb

@@ -345,30 +345,53 @@ describe Agents::HumanTaskAgent do
345 345
       @checker.memory['hits'].should == { "JH3132836336DHG" => { 'event_id' => @event.id } }
346 346
     end
347 347
 
348
-    it "should create events when all assignments are ready" do
349
-      @checker.memory['hits'] = { "JH3132836336DHG" => { 'event_id' => @event.id } }
350
-      mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
351
-      assignments = [
352
-        FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"neutral", "feedback"=>""}),
353
-        FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"happy", "feedback"=>"Take 2"})
354
-      ]
355
-      hit = FakeHit.new(:max_assignments => 2, :assignments => assignments)
356
-      hit.should_not be_disposed
357
-      mock(RTurk::Hit).new("JH3132836336DHG") { hit }
348
+    context "emitting events" do
349
+      before do
350
+        @checker.memory['hits'] = { "JH3132836336DHG" => { 'event_id' => @event.id } }
351
+        mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
352
+        @assignments = [
353
+          FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"neutral", "feedback"=>""}),
354
+          FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"happy", "feedback"=>"Take 2"})
355
+        ]
356
+        @hit = FakeHit.new(:max_assignments => 2, :assignments => @assignments)
357
+        @hit.should_not be_disposed
358
+        mock(RTurk::Hit).new("JH3132836336DHG") { @hit }
359
+      end
358 360
 
359
-      lambda {
360
-        @checker.send :review_hits
361
-      }.should change { Event.count }.by(1)
361
+      it "should create events when all assignments are ready" do
362
+        lambda {
363
+          @checker.send :review_hits
364
+        }.should change { Event.count }.by(1)
362 365
 
363
-      assignments.all? {|a| a.approved == true }.should be_truthy
364
-      hit.should be_disposed
366
+        @assignments.all? {|a| a.approved == true }.should be_truthy
367
+        @hit.should be_disposed
365 368
 
366
-      @checker.events.last.payload['answers'].should == [
367
-        {'sentiment' => "neutral", 'feedback' => ""},
368
-        {'sentiment' => "happy", 'feedback' => "Take 2"}
369
-      ]
369
+        @checker.events.last.payload['answers'].should == [
370
+          {'sentiment' => "neutral", 'feedback' => ""},
371
+          {'sentiment' => "happy", 'feedback' => "Take 2"}
372
+        ]
373
+
374
+        @checker.memory['hits'].should == {}
375
+      end
376
+
377
+      it "should emit separate answers when options[:separate_answers] is true" do
378
+        @checker.options[:separate_answers] = true
370 379
 
371
-      @checker.memory['hits'].should == {}
380
+        lambda {
381
+          @checker.send :review_hits
382
+        }.should change { Event.count }.by(2)
383
+
384
+        @assignments.all? {|a| a.approved == true }.should be_truthy
385
+        @hit.should be_disposed
386
+
387
+        event1, event2 = @checker.events.last(2)
388
+        event1.payload.should_not have_key('answers')
389
+        event2.payload.should_not have_key('answers')
390
+        event1.payload['answer'].should == { 'sentiment' => "happy", 'feedback' => "Take 2" }
391
+        event2.payload['answer'].should == { 'sentiment' => "neutral", 'feedback' => "" }
392
+
393
+        @checker.memory['hits'].should == {}
394
+      end
372 395
     end
373 396
 
374 397
     describe "taking majority votes" do